package com.cnsugar.common.jdbc;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

import com.cnsugar.common.jdbc.dialect.DialectUtils;
import com.cnsugar.common.jdbc.model.BatchModel;
import com.cnsugar.common.jdbc.model.SqlModel;
import com.cnsugar.common.context.AppContext;
import com.cnsugar.common.jdbc.utils.JdbcUtils;
import com.cnsugar.common.paging.Page;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * 数据库操作工具类
 *
 * @Author Sugar
 * @Version 2014-1-17下午1:46:32
 **/
public class DbUtils extends JdbcDaoSupport {
    protected static String JDBC_TEMPLATE = "jdbcTemplate";
    protected static Logger log = LoggerFactory.getLogger(DbUtils.class);
    protected static JdbcTemplate jdbcTemplate;

    /**
     *
     * 执行无返回值的存储过程
     *
     * @param callString
     *            存储过程语句
     */
    public static void execute(String callString) {
        execute(callString, getJdbcTemplate());
    }

    /**
     *
     * 执行无返回值的存储过程
     *
     * @param callString
     *            存储过程语句
     * @param args
     *            参数
     */
    public static void execute(String callString, Object[] args) {
        execute(callString, args, getJdbcTemplate());
    }

    /**
     *
     * 执行存储过程，返回String类型
     *
     * @param callString
     *            存储过程语句
     */
    public static String executeForString(String callString) {
        return executeForString(callString, null, getJdbcTemplate());
    }

    /**
     *
     * 执行存储过程，返回String类型
     *
     * @param callString
     *            存储过程语句
     * @param args
     *            参数
     */
    public static String executeForString(String callString, Object[] args) {
        return executeForString(callString, args, getJdbcTemplate());
    }

    /**
     *
     * 执行存储过程，返回int类型
     *
     * @param callString
     *            存储过程语句
     */
    public static int executeForInt(String callString) {
        return executeForInt(callString, null, getJdbcTemplate());
    }

    /**
     *
     * 执行存储过程，返回int类型
     *
     * @param callString
     *            存储过程语句
     * @param args
     *            参数
     */
    public static int executeForInt(String callString, Object[] args) {
        return executeForInt(callString, args, getJdbcTemplate());
    }

    /**
     *
     * 执行存储过程，返回List类型
     *
     * @param callString
     *            存储过程语句
     */
    public static List<Map<String, Object>> executeForList(String callString) {
        return executeForList(callString, null, getJdbcTemplate());
    }

    /**
     *
     * 执行存储过程，返回List类型
     *
     * @param callString
     *            存储过程语句
     * @param args
     *            参数
     */
    public static List<Map<String, Object>> executeForList(String callString, Object[] args) {
        return executeForList(callString, args, getJdbcTemplate());
    }

    /**
     *
     * 执行存储过程，返回Map类型
     *
     * @param callString
     *            存储过程语句
     */
    public static Map<String, Object> executeForMap(String callString) {
        return executeForMap(callString, null, getJdbcTemplate());
    }

    /**
     *
     * 执行存储过程，返回Map类型
     *
     * @param callString
     *            存储过程语句
     * @param args
     *            参数
     */
    public static Map<String, Object> executeForMap(String callString, Object[] args) {
        return executeForMap(callString, args, getJdbcTemplate());
    }

    /**
     *
     * update语句
     *
     * @param wsql
     *            DDL语句
     */
    public static int update(String wsql) {
        return update(wsql, null, getJdbcTemplate());
    }

    /**
     *
     * update语句
     *
     * @param wsql
     *            DDL语句
     * @param jt
     *            JdbcTemplate
     */
    public static int update(String wsql, JdbcTemplate jt) {
        return update(wsql, null, jt);
    }

    /**
     *
     * update语句
     *
     * @param wsql
     *            DDL语句
     * @param args
     *            参数
     */
    public static int update(String wsql, Object[] args) {
        return update(wsql, args, getJdbcTemplate());
    }

    /**
     *
     * 增加、删除、修改表时，调用此方法
     *
     * @param wsql
     *            DDL语句
     * @param args
     *            参数
     * @param jt
     *            JdbcTemplate
     *
     */
    public static int update(String wsql, Object[] args, JdbcTemplate jt) {
        return update(wsql, args, null, jt);
    }

    /**
     * 批量更新
     *
     * @param sql
     * @param valueList
     * @return
     */
    public static int batchUpdate(String sql, final List<Object[]> valueList) {
        return batchUpdate(sql, valueList, null, getJdbcTemplate());
    }

    /**
     * 批量更新
     *
     * @param sql
     * @param valueList
     * @param types
     *            java.sql.Types
     * @return
     */
    public static int batchUpdate(String sql, final List<Object[]> valueList, final int[] types) {
        return batchUpdate(sql, valueList, types, getJdbcTemplate());
    }

    /**
     * 批量更新
     *
     * @param sql
     * @return
     */
    public static int batchUpdate(String[] sql) {
        return batchUpdate(sql, getJdbcTemplate());
    }

    /**
     * 批量更新
     *
     * @param sql
     * @param jt
     * @return
     */
    public static int batchUpdate(String[] sql, JdbcTemplate jt) {
        String logstr = null;
        if (log.isDebugEnabled()) {
            logstr = "batchUpdate: sql=" + sql + "; parameters=" + arrayToString(sql);
            log.debug(logstr);
        }
        int[] rows = jt.batchUpdate(sql);
        int total = 0;
        for (int r : rows) {
            total += r;
        }
        if (log.isInfoEnabled()) {
            if (logstr == null) {
                logstr = "batchUpdate: sql=" + sql + "; parameters=" + arrayToString(sql);
            }
            log.info(logstr + "; rows=" + total);
        }
        return total;
    }

    /**
     *
     * 执行insert语句
     *
     * @param wsql
     *            wsql语句
     *
     */
    public static int insert(String wsql) {
        return insert(wsql, null, getJdbcTemplate());
    }

    /**
     *
     * 执行insert语句
     *
     * @param wsql
     *            wsql语句
     * @param args
     *            参数
     *
     */
    public static int insert(String wsql, Object[] args) {
        return insert(wsql, args, getJdbcTemplate());
    }

    /**
     *
     * 执行insert语句
     *
     * @param wsql
     *            wsql语句
     * @param jt
     *            JdbcTemplate
     *
     */
    public static int insert(String wsql, JdbcTemplate jt) {
        return insert(wsql, null, jt);
    }

    /**
     *
     * 执行insert语句
     *
     * @param wsql
     *            wsql语句
     * @param args
     *            参数
     * @param jt
     *            JdbcTemplate
     *
     */
    public static int insert(String wsql, Object[] args, JdbcTemplate jt) {
        String logstr = null;
        if (log.isDebugEnabled()) {
            logstr = "insert: sql=" + wsql + "; parameters=" + arrayToString(args);
            log.debug(logstr);
        }
        int rows = jt.update(wsql, args);
        if (log.isInfoEnabled()) {
            if (logstr == null) {
                logstr = "insert: sql=" + wsql + "; parameters=" + arrayToString(args);
            }
            log.info(logstr + "; rows=" + rows);
        }
        return rows;
    }

    /**
     *
     * 删除表中的记录
     *
     * @param wsql
     *            sql或删除条件 如：( id>? and time>?)
     *
     * @return 返回删除的条数
     */

    public static int delete(String wsql) {
        return delete(wsql, null, getJdbcTemplate());
    }

    /**
     * * 删除表中的记录
     *
     * @param wsql
     *            sql 或 删除条件 如：( id>? and time>?)
     *
     * @param whereArgs
     *            条件里的参数 用来替换"?" 第1个参数，代表第1个问号；第2个参数，代表第2个问号；依此类推......
     *
     * @return 返回删除的条数
     */
    public static int delete(String wsql, Object[] whereArgs) {
        return delete(wsql, whereArgs, getJdbcTemplate());
    }

    /**
     * * 删除表中的记录
     *
     * @param wsql
     *            sql 或 删除条件 如：( id>? and time>?)
     *
     * @param jt
     *            SpringJdbcTemplate
     * @return 返回删除的条数
     */
    public static int delete(String wsql, JdbcTemplate jt) {
        return delete(wsql, null, jt);
    }

    /**
     * * 删除表中的记录
     *
     * @param wsql
     *            sql 或 删除条件 如：( id>? and time>?)
     *
     * @param whereArgs
     *            条件里的参数 用来替换"?" 第1个参数，代表第1个问号；第2个参数，代表第2个问号；依此类推......
     *
     * @param jt
     *            SpringJdbcTemplate
     * @return 返回删除的条数
     */
    public static int delete(String wsql, Object[] whereArgs, JdbcTemplate jt) {
        String logstr = null;
        if (log.isDebugEnabled()) {
            logstr = "delete: sql=" + wsql + "; parameters=" + arrayToString(whereArgs);
            log.debug(logstr);
        }
        int rows = 0;
        if (whereArgs != null && whereArgs.length > 0) {
            rows = jt.update(wsql, whereArgs);
        } else {
            rows = jt.update(wsql);
        }
        if (log.isInfoEnabled()) {
            if (logstr == null) {
                logstr = "delete: sql=" + wsql + "; parameters=" + arrayToString(whereArgs);
            }
            log.info(logstr + "; rows=" + rows);
        }
        return rows;
    }

    /**
     * 返回int类型
     *
     * @param wsql
     *            where条件或完整的sql
     * @return
     */
    public static int queryForInt(String wsql) {
        return queryForInt(wsql, null, null, getJdbcTemplate());
    }

    /**
     * 返回int类型
     *
     * @param wsql
     * @param jt
     * @return
     */
    public static int queryForInt(String wsql, JdbcTemplate jt) {
        return queryForInt(wsql, null, null, jt);
    }

    /**
     * 返回int类型
     *
     * @param wsql
     * @param values
     * @return
     */
    public static int queryForInt(String wsql, Object[] values) {
        return queryForInt(wsql, values, null, getJdbcTemplate());
    }

    /**
     * 返回int类型
     *
     * @param wsql
     * @param values
     * @param jt
     * @return
     */
    public static int queryForInt(String wsql, Object[] values, JdbcTemplate jt) {
        return queryForInt(wsql, values, null, jt);
    }

    /**
     * 返回int类型
     *
     * @param wsql
     * @param values
     * @param types
     * @return
     */
    public static int queryForInt(String wsql, Object[] values, int[] types) {
        return queryForInt(wsql, values, types, getJdbcTemplate());
    }

    /**
     * 返回int类型
     *
     * @param wsql
     *            where条件或完整的sql
     * @return
     */
    public static long queryForLong(String wsql) {
        return queryForLong(wsql, null, null, getJdbcTemplate());
    }

    /**
     * 返回long类型
     *
     * @param wsql
     * @param jt
     * @return
     */
    public static long queryForLong(String wsql, JdbcTemplate jt) {
        return queryForLong(wsql, null, null, jt);
    }

    /**
     * 返回long类型
     *
     * @param wsql
     * @param values
     * @return
     */
    public static long queryForLong(String wsql, Object[] values) {
        return queryForLong(wsql, values, null, getJdbcTemplate());
    }

    /**
     * 返回long类型
     *
     * @param wsql
     * @param values
     * @param jt
     * @return
     */
    public static long queryForLong(String wsql, Object[] values, JdbcTemplate jt) {
        return queryForLong(wsql, values, null, jt);
    }

    /**
     * 返回long类型
     *
     * @param wsql
     * @param values
     * @param types
     * @return
     */
    public static long queryForLong(String wsql, Object[] values, int[] types) {
        return queryForLong(wsql, values, types, getJdbcTemplate());
    }

    /**
     * 返回String类型
     *
     * @param wsql
     *            where条件或完整的sql
     * @return
     */
    public static String queryForString(String wsql) {
        return queryForString(wsql, null, null, getJdbcTemplate());
    }

    /**
     * 返回String类型
     *
     * @param wsql
     * @param jt
     * @return
     */
    public static String queryForString(String wsql, JdbcTemplate jt) {
        return queryForString(wsql, null, null, jt);
    }

    /**
     * 返回String类型
     *
     * @param wsql
     * @param values
     * @return
     */
    public static String queryForString(String wsql, Object[] values) {
        return queryForString(wsql, values, null, getJdbcTemplate());
    }

    /**
     * 返回String类型
     *
     * @param wsql
     * @param values
     * @param jt
     * @return
     */
    public static String queryForString(String wsql, Object[] values, JdbcTemplate jt) {
        return queryForString(wsql, values, null, jt);
    }

    /**
     * 返回String类型
     *
     * @param wsql
     * @param values
     * @param types
     * @return
     */
    public static String queryForString(String wsql, Object[] values, int[] types) {
        return queryForString(wsql, values, types, getJdbcTemplate());
    }

    /**
     * 返回Map<String,String>对象
     *
     * @param wsql
     * @return
     */
    public static Map<String, Object> queryForMap(String wsql) {
        return queryForMap(wsql, null, null, getJdbcTemplate());
    }

    public static Map<String, Object> queryForMap(String wsql, JdbcTemplate jt) {
        return queryForMap(wsql, null, null, jt);
    }

    /**
     * 返回Map<String,String>对象
     *
     * @param wsql
     * @param values
     * @return
     */
    public static Map<String, Object> queryForMap(String wsql, Object[] values) {
        return queryForMap(wsql, values, null, getJdbcTemplate());
    }

    /**
     * 返回Map<String,String>对象
     *
     * @param wsql
     * @param values
     * @param types
     * @return
     */
    public static Map<String, Object> queryForMap(String wsql, Object[] values, int[] types) {
        return queryForMap(wsql, values, types, getJdbcTemplate());
    }

    /**
     * 返回Map<String,String>对象
     *
     * @param wsql
     * @param values
     * @param jt
     * @return
     */
    public static Map<String, Object> queryForMap(String wsql, Object[] values, JdbcTemplate jt) {
        return queryForMap(wsql, values, null, jt);
    }

    /**
     * 通过SQL查询一个对象的所有信息，只返回一条记录
     *
     * @param obj
     *            Object 需要查询的对象，这个对象是对数据库映射的一个javabean
     * @param wsql
     *            String 查询的语句
     * @return object Object 查询的结果
     */
    public static <T> T queryForObject(final Class<T> obj, String wsql) {
        return queryForObject(obj, wsql, null, null, getJdbcTemplate());
    }

    public static <T> T queryForObject(final Class<T> obj, String wsql, JdbcTemplate jt) {
        return queryForObject(obj, wsql, null, null, jt);
    }

    public static <T> T queryForObject(final Class<T> obj, String wsql, Object[] values) {
        return queryForObject(obj, wsql, values, null, getJdbcTemplate());
    }

    public static <T> T queryForObject(final Class<T> obj, String wsql, Object[] values, JdbcTemplate jt) {
        return queryForObject(obj, wsql, values, null, jt);
    }

    public static <T> T queryForObject(final Class<T> obj, String wsql, Object[] values, int[] types) {
        return queryForObject(obj, wsql, values, types, getJdbcTemplate());
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param clazz
     * @param wsql
     * @param wsql
     * @return
     */
    public static <T> List<T> queryForList(final Class<T> clazz, String wsql) {
        return queryForList(clazz, wsql, null, null, getJdbcTemplate());
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param clazz
     *            <T>
     * @param wsql
     * @param jt
     * @return
     */
    public static <T> List<T> queryForList(final Class<T> clazz, String wsql, JdbcTemplate jt) {
        return queryForList(clazz, wsql, null, null, jt);
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param clazz
     *            <T>
     * @param wsql
     * @param values
     * @return
     */
    public static <T> List<T> queryForList(final Class<T> clazz, String wsql, Object[] values) {
        return queryForList(clazz, wsql, values, null, getJdbcTemplate());
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param clazz
     *            <T>
     * @param wsql
     * @param values
     * @param jt
     * @return
     */
    public static <T> List<T> queryForList(final Class<T> clazz, String wsql, Object[] values, JdbcTemplate jt) {
        return queryForList(clazz, wsql, values, null, jt);
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param clazz
     *            <T>
     * @param wsql
     * @param orderBy
     * @return
     */
    public static <T> List<T> queryForList(final Class<T> clazz, String wsql, String orderBy) {
        return queryForList(clazz, wsql, null, orderBy, getJdbcTemplate());
    }

    /**
     * 从指定表中查询某个对象的列表，返回多条记录
     *
     * @param clazz
     *            <T>
     * @param wsql
     * @param values
     * @param orderBy
     * @return
     */
    public static <T> List<T> queryForList(final Class<T> clazz, String wsql, Object[] values, String orderBy) {
        return queryForList(clazz, wsql, values, orderBy, getJdbcTemplate());
    }

    /**
     * 返回一个List<Map>
     *
     * @param sql
     * @return
     */
    public static List<Map<String, Object>> queryForMapList(String sql) {
        return queryForMapList(sql, null, null, getJdbcTemplate());
    }

    /**
     * 返回一个List<Map>
     *
     * @param sql
     * @param values
     * @return
     */
    public static List<Map<String, Object>> queryForMapList(String sql, Object[] values) {
        return queryForMapList(sql, values, null, getJdbcTemplate());
    }

    /**
     * 返回一个List<Map>
     *
     * @param sql
     * @param values
     * @param types
     * @return
     */
    public static List<Map<String, Object>> queryForMapList(String sql, Object[] values, int[] types) {
        return queryForMapList(sql, values, types, getJdbcTemplate());
    }

    /**
     * 返回一个List<Map>
     *
     * @param sql
     * @param jt
     * @return
     */
    public static List<Map<String, Object>> queryForMapList(String sql, JdbcTemplate jt) {
        return queryForMapList(sql, null, null, jt);
    }

    /**
     * 返回一个List<Map>
     *
     * @param sql
     * @param values
     * @param jt
     * @return
     */
    public static List<Map<String, Object>> queryForMapList(String sql, Object[] values, JdbcTemplate jt) {
        return queryForMapList(sql, values, null, jt);
    }

    /**
     * 返回一个List<Integer>
     *
     * @param sql
     * @return List<Integer>
     */
    public static List<Integer> queryForIntegerList(String sql) {
        return queryForIntegerList(sql, null, false, getJdbcTemplate());
    }

    /**
     * 返回一个List<Integer>
     *
     * @param sql
     * @param values
     * @return List<Integer>
     */
    public static List<Integer> queryForIntegerList(String sql, Object[] values) {
        return queryForIntegerList(sql, values, false, getJdbcTemplate());
    }

    /**
     * 返回一个List<Integer>
     *
     * @param sql
     * @param unique
     *            返回结果是否去重 ture是
     * @return List<Integer>
     */
    public static List<Integer> queryForIntegerList(String sql, final boolean unique) {
        return queryForIntegerList(sql, null, unique, getJdbcTemplate());
    }

    /**
     * 返回一个List<Integer>
     *
     * @param sql
     * @param values
     * @param unique
     *            返回结果是否去重 ture是
     * @return List<Integer>
     */
    public static List<Integer> queryForIntegerList(String sql, Object[] values, final boolean unique) {
        return queryForIntegerList(sql, values, unique, getJdbcTemplate());
    }

    /**
     * 返回一个List<Long>
     *
     * @param sql
     * @return List<Long>
     */
    public static List<Long> queryForLongList(String sql) {
        return queryForLongList(sql, null, false, getJdbcTemplate());
    }

    /**
     * 返回一个List<Long>
     *
     * @param sql
     * @param values
     * @return List<Long>
     */
    public static List<Long> queryForLongList(String sql, Object[] values) {
        return queryForLongList(sql, values, false, getJdbcTemplate());
    }

    /**
     * 返回一个List<Long>
     *
     * @param sql
     * @param unique
     *            返回结果是否去重 ture是
     * @return List<Long>
     */
    public static List<Long> queryForLongList(String sql, final boolean unique) {
        return queryForLongList(sql, null, unique, getJdbcTemplate());
    }

    /**
     * 返回一个List<Long>
     *
     * @param sql
     * @param values
     * @param unique
     *            返回结果是否去重 ture是
     * @return List<Long>
     */
    public static List<Long> queryForLongList(String sql, Object[] values, final boolean unique) {
        return queryForLongList(sql, values, unique, getJdbcTemplate());
    }

    /**
     * 返回一个List<String>
     *
     * @param sql
     * @return List<String>
     */
    public static List<String> queryForStringList(String sql) {
        return queryForStringList(sql, null, false, getJdbcTemplate());
    }

    /**
     * 返回一个List<String>
     *
     * @param sql
     * @param values
     * @return List<String>
     */
    public static List<String> queryForStringList(String sql, Object[] values) {
        return queryForStringList(sql, values, false, getJdbcTemplate());
    }

    /**
     * 返回一个List<String>
     *
     * @param sql
     * @param unique
     *            返回结果是否去重 ture是
     * @return List<String>
     */
    public static List<String> queryForStringList(String sql, final boolean unique) {
        return queryForStringList(sql, null, unique, getJdbcTemplate());
    }

    /**
     * 返回一个List<Integer>
     *
     * @param sql
     * @param values
     * @param unique
     *            返回结果是否去重 ture是
     * @return List<String>
     */
    public static List<String> queryForStringList(String sql, Object[] values, final boolean unique) {
        return queryForStringList(sql, values, unique, getJdbcTemplate());
    }

    /**
     * 查询分页对象
     *
     * @param page
     * @param wsql
     * @return
     */
    public static <T> Page queryForPage(Page page, String wsql) {
        return queryForPage(page, wsql, null, getJdbcTemplate());
    }

    /**
     * 查询分页对象
     *
     * @param page
     * @param wsql
     * @return
     */
    public static <T> Page queryForPage(Page page, String wsql, JdbcTemplate jt) {
        return queryForPage(page, wsql, null, jt);
    }

    /**
     * 查询分页对象
     *
     * @param page
     * @param wsql
     * @param values
     * @return
     */
    public static <T> Page queryForPage(Page page, String wsql, Object[] values) {
        return queryForPage(page, wsql, values, getJdbcTemplate());
    }

    /**
     * 查询分页对象，结果集中存Map对象
     *
     * @param page
     * @param wsql
     * @return
     */
    public static Page queryForMapPage(Page page, String wsql) {
        return queryForPageWithMap(page, wsql, null, getJdbcTemplate());
    }

    /**
     * 查询分页对象，结果集中存Map对象
     *
     * @param page
     * @param wsql
     * @param jt
     * @return
     */
    public static Page queryForMapPage(Page page, String wsql,
                                       JdbcTemplate jt) {
        return queryForPageWithMap(page, wsql, null, jt);
    }

    /**
     * 查询分页对象，结果集中存Map对象
     *
     * @param page
     * @param wsql
     * @param values
     * @return
     */
    public static Page queryForMapPage(Page page, String wsql,
                                       Object[] values) {
        return queryForPageWithMap(page, wsql, values, getJdbcTemplate());
    }

    /**
     *
     * 根据1个java对象更新数据库对应的表，表名跟类名一样
     *
     * @param object
     *            Object 需要更新的对象，这个对象是对数据库映射的一个javabean
     */
    public static <T> int update(T object) {
        return update(object, null, false, getJdbcTemplate());
    }

    /**
     *
     * 根据1个java对象更新数据库对应的表，表名跟类名一样
     *
     * @param t
     *            Object 需要更新的对象，这个对象是对数据库映射的一个javabean
     * @param jt
     * @return
     */
    public static <T> int update(T t, JdbcTemplate jt) {
        return update(t, null, false, jt);
    }

    /**
     * 根据1个java对象更新数据库对应的表
     *
     * @param t
     *            对象
     * @param fields
     *            需要更新的列名
     * @return
     */
    public static <T> int update(T t, String[] fields) {
        return update(t, fields, false, getJdbcTemplate());
    }

    /**
     * 根据1个java对象更新数据库对应的表
     *
     * @param t
     * @param fields
     * @param ignore
     * @return
     */
    public static <T> int update(T t, String[] fields, boolean ignore) {
        return update(t, fields, ignore, getJdbcTemplate());
    }

    /**
     * 根据1个java对象更新数据库对应的表
     *
     * @param t
     *            对象
     * @param fields
     *            需要更新的列名
     * @param jt
     * @return
     */
    public static <T> int update(T t, String[] fields, boolean ignore, JdbcTemplate jt) {
        SqlModel sqlModel;
        try {
            sqlModel = JdbcUtils.buildUpdateModel(t, fields, ignore, DialectUtils.getDialect(jt).getMark());
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
                | SecurityException e) {
            throw new DbException(e);
        }
        return update(sqlModel.sql, sqlModel.values, null, jt);
    }

    /**
     * 批量更新对象
     *
     * @param list
     *            对象列表
     * @param columns
     *            需要更新的列名
     * @return
     */
    public static <T> int batchUpdate(List<T> list, String[] columns) {
        return batchUpdate(list, columns, getJdbcTemplate());
    }

    /**
     * 批量更新对象
     *
     * @param list
     *            对象列表
     * @return 返回影响行数
     */
    public static <T> int batchUpdate(List<T> list) {
        return batchUpdate(list, null, getJdbcTemplate());
    }

    /**
     * 批量更新对象
     *
     * @param list
     *            对象列表
     * @param jt
     * @return 返回影响行数
     */
    public static <T> int batchUpdate(List<T> list, JdbcTemplate jt) {
        return batchUpdate(list, null, jt);
    }

    /**
     * 批量更新对象
     *
     * @param list
     *            对象列表
     * @param columns
     *            需要更新的列名
     * @param jt
     * @return
     */
    public static <T> int batchUpdate(List<T> list, String[] columns, JdbcTemplate jt) {
        BatchModel model;
        try {
            model = JdbcUtils.buildBatchUpdateModel(list, columns, false, DialectUtils.getDialect(jt).getMark());
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
                | SecurityException e) {
            throw new DbException(e);
        }
        return batchUpdate(model.sql, model.valueList, model.types, jt);
    }

    /**
     * 将一个对象插入数据库
     *
     * @param object
     *            Object 需要插入的对象，这个对象是对数据库映射的一个javabean
     * @return 返回主键ID
     */
    public static <T> long save(T object) {
        return save(object, getJdbcTemplate());
    }

    /**
     * 将一个对象插入数据库
     *
     * @param t
     *            t 需要插入的对象，这个对象是对数据库映射的一个javabean
     * @param jt
     *            JdbcTemplate
     * @return 返回主键ID
     */
    public static <T> long save(T t, final JdbcTemplate jt) {
        SqlModel sqlModel;
        try {
            sqlModel = JdbcUtils.buildSaveModel(t, DialectUtils.getDialect(jt).getMark());
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
                | SecurityException e) {
            throw new DbException(e);
        }
        return save(sqlModel.sql, sqlModel.values, sqlModel.types, sqlModel.pk, jt);
    }

    /**
     * 新增数据并返回自增主键的值
     *
     * @param sql insert语句
     * @param values insert的值参数列表
     * @param pkName 主键字段名
     * @return
     */
    public static long save(final String sql, final Object[] values, final String pkName) {
        return save(sql, values, pkName, getJdbcTemplate());
    }

    /**
     * 将一个对象插入数据库
     *
     * @param object
     *            Object 需要插入的对象，这个对象是对数据库映射的一个javabean
     * @return 返回主键ID
     */
    public static <T> boolean insert(T object) {
        return insert(object, getJdbcTemplate());
    }

    /**
     * 将一个对象插入数据库
     *
     * @param
     *            t 需要插入的对象，这个对象是对数据库映射的一个javabean
     * @param jt
     *            JdbcTemplate
     * @return
     */
    public static <T> boolean insert(T t, final JdbcTemplate jt) {
        SqlModel sqlModel;
        try {
            sqlModel = JdbcUtils.buildSaveModel(t, DialectUtils.getDialect(jt).getMark());
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
                | SecurityException e) {
            throw new DbException(e);
        }
        return insert(sqlModel.sql, sqlModel.values, sqlModel.types, jt);
    }

    /**
     * 批量新增对象
     *
     * @param list
     *            List<T> 需要插入的对象，这个对象是对数据库映射的一个javabean
     * @return 返回影响行数
     */
    public static <T> int batchSave(List<T> list) {
        return batchSave(list, getJdbcTemplate());
    }

    /**
     * 批量新增对象
     *
     * @param list
     *            List<T> 需要插入的对象，这个对象是对数据库映射的一个javabean
     * @param jt
     *            JdbcTemplate
     * @return 返回影响行数
     */
    public static <T> int batchSave(List<T> list, JdbcTemplate jt) {
        BatchModel model;
        try {
            model = JdbcUtils.buildBatchSaveModel(list, DialectUtils.getDialect(jt).getMark());
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
                | SecurityException e) {
            throw new DbException(e);
        }
        return batchUpdate(model.sql, model.valueList, model.types, jt);
    }

    /**
     * 保存或更新对象,返回对象ID
     *
     * @param t
     * @return 返回对象ID
     */
    public static <T> boolean saveOrUpdate(T t) {
        try {
            return saveOrUpdate(t, getJdbcTemplate());
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
                | SecurityException e) {
            throw new DbException(e);
        }
    }

    /**
     * 是否存在
     *
     * @param wsql
     * @return
     */
    public static boolean exists(String wsql) {
        return exists(wsql, getJdbcTemplate());
    }

    /**
     * 是否存在
     *
     * @param wsql
     * @param jt
     * @return
     */
    public static boolean exists(String wsql, JdbcTemplate jt) {
        return exists(wsql, null, jt);
    }

    /**
     * 是否存在
     *
     * @param wsql
     * @param values
     * @return
     */
    public static boolean exists(String wsql, Object[] values) {
        return exists(wsql, values, getJdbcTemplate());
    }

    /**
     * 是否存在
     *
     * @param wsql
     * @param values
     * @param jt
     * @return
     */
    public static boolean exists(String wsql, Object[] values, JdbcTemplate jt) {
        boolean flag = false;
        try {
            Integer r = jt.queryForObject(wsql, values, Integer.class);
            if (r != null && r.intValue() > 0) {
                flag = true;
            }
        } catch (EmptyResultDataAccessException e) {
        }
        if (log.isInfoEnabled()) {
            log.info("exists: sql=" + wsql + "; parameters=" + arrayToString(values) + "; result=" + flag);
        }
        return flag;
    }

    /**
     * 返回JdbcTemplate对象
     *
     * @return
     */
    public static JdbcTemplate getJdbcTemplate() {
        if (jdbcTemplate != null) {
            return jdbcTemplate;
        }
        return (JdbcTemplate) AppContext.getBean(JDBC_TEMPLATE);
    }
}
